package cn.pink.core.support;

import cn.hutool.core.util.ReflectUtil;
import cn.pink.core.entity.AbstractEntity;
import cn.pink.core.gen.entity.Entity;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Map;

/**
 * @Author: pink
 * @Date: 2022/7/26 16:15
 */
public class EntityUtils {
    /**
     * 获取key类型
     */
    public static Class<?> getKeyType(Class<?> clazz){
        Entity table = clazz.getAnnotation(Entity.class);
        return ReflectUtil.getField(clazz, table.key()).getType();
    }

    /**
     * 获取setXXXX 的属性名
     */
    public static String getAttrByMethod(String methodName) {
        String firstLetter = methodName.substring(3, 4).toLowerCase();
        return firstLetter + methodName.substring(4);
    }

    /**
     * 通过属性名获取settor方法名
     */
    public static String getSetterName(Field field) {
        String fieldName = field.getName();
        //获得字段第一个字母大写
        String firstLetter = field.getName().substring(0, 1).toUpperCase();
        if (field.getType() == boolean.class || field.getType() == Boolean.class){
            if (fieldName.startsWith("is")){
                if (fieldName.length() > 2 && Character.isUpperCase(fieldName.charAt(2))){
                    return "set"+fieldName.substring(2);
                }
            }
        }
        //转换成字段的set方法
        return "set" + firstLetter + field.getName().substring(1);
    }

    /**
     * 通过属性名获取gettor方法名
     */
    public static String getGetterName(Field field) {
        String fieldName = field.getName();
        //获得字段第一个字母大写
        String firstLetter = fieldName.substring(0, 1).toUpperCase();
        //转换成字段的get方法
        if (field.getType() == boolean.class || field.getType() == Boolean.class){
            if (fieldName.startsWith("is")){
                return fieldName;
            } else {
                return "is" + firstLetter + fieldName.substring(1);
            }
        }

        return "get" + firstLetter + fieldName.substring(1);
    }

    /**
     * 通过key获取对应的字段名
     */
    public static String getFiledByKey(String key) {
        String[] keys = key.split("\\.");
        return keys[keys.length - 1];
    }

    /**
     * 根据basetype的类型和值生成对应的实例
     */
    public static String generateTypeString(Class<?> paramClass, Object value) {
        if (int.class == paramClass || String.class == paramClass ||
                Long.class == paramClass || long.class == paramClass|| Byte.class == paramClass ||
                Short.class == paramClass){
            return value.toString();
        }else if(Boolean.class == paramClass||boolean.class==paramClass){
            return (boolean)value?"1":"0";
        }

        return GsonUtil.toJson(value);
    }

    /**
     * 根据paramClass的类型和值生成对应的实例
     */
    public static Object generateTypeClass(Class<?> paramClass, String value, Type typeOfT) {
        if (int.class == paramClass){
            return Integer.parseInt(value);
        }
        else if (String.class == paramClass) {
            return value;
        }
        else if (Long.class == paramClass || long.class == paramClass) {
            return Long.parseLong(value);
        }
        else if (Byte.class == paramClass) {
            return Byte.parseByte(value);
        }
        else if (Short.class == paramClass) {
            return Short.parseShort(value);
        }
        else if (Boolean.class == paramClass) {
            return "1".equals(value);
        }

        return GsonUtil.fromJson(value, typeOfT);
    }

    /**
     * 初始化entity数据
     */
    public static void initEntity(Class<?> clazz, AbstractEntity entity, Map<String, Object> data) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (Modifier.isTransient(field.getModifiers())) {
                continue;
            }

            String fieldName = field.getName();

            Object value = data.get(fieldName);
            if (null == value) {
                continue;
            }

            String setMethodName = getSetterName(field);

            try {
                Object val = generateTypeClass(field.getType(), (String) value, field.getGenericType());
                if(val == null) {
                    continue;
                }

                Method setMethod = clazz.getDeclaredMethod(setMethodName, field.getType());
                setMethod.invoke(entity, val);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
